/*
 * bsp_socket.h
 *
 * Copyright (C) 2011 - Dr.NP
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @version bsp_socket.h 1.0.0
 * @package libbspcore
 * @author Dr.NP <np@bsgroup.org>
 * @update 03/21/2011
 */

#ifndef BSP_SOCKET_H

#define BSP_SOCKET_H                            1

#include <time.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// Defination
#define SERVER_LIST_INITIAL                     32
#define CLIENT_LIST_INITIAL                     1024
#define CONNECTOR_LIST_INITIAL                  1024

#define TRANSPORT_LOCAL                         0b00000001
#define TRANSPORT_TCP                           0b00000010
#define TRANSPORT_UDP                           0b00000100

#define EPOLL_MODE_LT                           0b00010000
#define EPOLL_MODE_ET                           0x00100000

#define NET_IPV4                                0x01000000
#define NET_IPV6                                0x10000000

#define SOCKET_RCVBUF                           65536
#define SOCKET_SNDBUF                           65536
#define SOCKET_LISTEN_QUEUES                    1024
#define EPOLL_WAIT_CONNS                        1024

#define CLIENT_BUFFER_INITIAL                   65536
#define CLIENT_BUFFER_HIGHWAT                   1048576

#define ADDR_DSP_LENGTH                         64

#define DEBUG_DATA                              0

// Macros

// Structs
struct server_t
{
    int id;                                     // Server id
    int fd;                                     // File descriptor
    int conn_type;                              // TCP / UDP / UNIX
    int epoll_mode;                             // Sets of ET(Edge Triggered) or LT(Level Triggered)(Which is the default mode of epoll)
    int net_type;                               // IPv4 / IPv6
    char srv_addr[ADDR_DSP_LENGTH];             // IPv4 / 6 address (string)
    int srv_port;                               // Server port(0 - 65535)
    int in_use;
    time_t start_time;
    int app_id;                                 // App id

    /* Callbacks */
    size_t (* on_data) (int, char *, size_t);   // Callback on data event
    void (* on_conn) (int);                     // Callback on connect
    void (* on_close) (int);                    // Callback on client disconnect

    struct sockaddr_in listen_addr;             // IPv4
    struct sockaddr_in6 listen_addr6;           // IPv6
    struct sockaddr_un local_addr;              // Local IPC
    struct epoll_event ev;                      // Epoll event object

    // Status
    int clients;
    u_int64_t bytes_read;
    u_int64_t bytes_sent;
};

struct client_t
{
    int id;
    int fd;
    int srv_id;
    int worker_id;
    int conn_type;
    int epoll_mode;
    int net_type;
    //u_int32_t remote_addr;
    int remote_port;
    int in_use;

    size_t read_buffer_size;
    int read_buffer_data_size;
    int read_buffer_data_cur;
    //int pack_buffer_size;
    char *read_buffer;
    size_t send_buffer_size;
    int send_buffer_data_size;
    int send_buffer_data_cur;
    char *send_buffer;
    
    struct iovec *iov;
    int iov_size;
    int iov_used;
    struct msghdr *msg;
    int msg_size;
    int msg_used;
    
    struct epoll_event ev;
    struct sockaddr_in client_addr;
    struct sockaddr_in6 client_addr6;
    struct sockaddr_un local_addr;
};

struct connector_t
{
    int id;
    int fd;
    int worker_id;
    int conn_type;
    int epoll_mode;
    int net_type;
    char srv_addr[ADDR_DSP_LENGTH];
    int remote_port;
    int in_use;

    size_t read_buffer_size;
    int read_buffer_data_size;
    int read_buffer_data_cur;
    char *read_buffer;
    size_t send_buffer_size;
    int send_buffer_data_size;
    int send_buffer_data_cur;
    char *send_buffer;
    
    struct epoll_event ev;
    struct sockaddr_in remote_addr;             // IPv4
    struct sockaddr_in6 remote_addr6;           // IPv6
    struct sockaddr_un local_addr;              // Local IPC

    int (* on_data) (int, char *, size_t);
    void (* on_conn) (int);
    void (* on_close) (int);

    u_int64_t bytes_read;
    u_int64_t bytes_sent;
};

// Functions
int socket_init();

int new_server(int, const char *, u_int16_t);
int close_server();
struct server_t * get_server(int);

int accept_client(struct server_t *);
int close_client();
struct client_t * get_client(int);
int append_client(int, const char *, size_t);
int read_client(int);
int send_client(int);

int new_connector(int, const char *, u_int16_t);
int close_connector();
struct connector_t * get_connector(int);
int append_connector(int, const char *, size_t);
int read_connector(int);
int send_connector(int);

int send_data();

#endif  /* bsp_socket.h */
